#include <iostream>
#include <signal.h>
#include <fstream>

#include "../comm/httplib.h"
#include "oj_control.hpp"
#include "../comm/util.hpp"

#include <jsoncpp/json/json.h>

static ns_control::Control *ptr_control = nullptr;

std::string GetFileContentHeader(const std::string &path)
    {

        // std::ifstream in(path, std::ios::binary); // 以二进制读取文件
        // if (!in.is_open())                        // 如果文件打开失败，直接返回
        //     return "";

        // std::string content, line;
        // while (getline(in, line))
        //     content += line;
        // // in >> content;
        // in.close();
        // return content;

        std::ifstream in(path, std::ios::binary);
        if (!in.is_open())
        {
            
             return "";
        }
        // 打开文件后，将文件流移动到文件的最结尾
        in.seekg(0, in.end);
        int filesize = in.tellg(); // 读取文件的偏移量，因为我们移动到结尾，读取到的就是文件的总大小

        // 读取到大小后，再将文件流移动到 文件的最开始
        in.seekg(0, in.beg);

        std::string content;
        // 将字符串的大小调整成文件的大小
        content.resize(filesize);
        in.read((char *)content.c_str(), filesize); // 从content的起始位置开始读取，读取filesize个字节

        // 上面的步骤最好用vector来实现
        // std::vector<char> content(filesize);
        // in.read(content.data(),filesize);  // content.data() 容器的起始地址
        // // read 方法 从content容器的起始地址开始填充，填充filesize大小

        in.close();
        return content;
    }


void Recovery(int signo)
{
    ptr_control->RecoveryMachines();
}

int main()
{
    // Ctrl + 'z'
    signal(SIGTSTP,Recovery);   // 重新上线主机
    
    
    // 用户请求的服务路由功能

    // 获取所有的题目列表
    // 用户根据题目编号,获取题目的内容
    // 用户提交代码,判题功能

    httplib::Server svr;
    ns_control::Control control;

    ptr_control = &control;

    //  lambada 要使用外部表达式,需要引用外部对象
    svr.Get("/all_questions", [&control](const httplib::Request &_request, httplib::Response &_response)
    {
        std::string html;
        control.AllQuestions(&html);
        _response.set_content(html,"text/html; charset=utf-8");
    });

    svr.Get("/all_questions1", [&control](const httplib::Request &_request, httplib::Response &_response)
    {
        std::string html;
        control.AllQuestions_table(&html);
        _response.set_content(html,"text/html; charset=utf-8");
    });


    //  R"()"  原生字符,保持字符串的原貌
                       //  \d+  正则表达式:  \d  (匹配数字)  \d+ (匹配一个或多个数字)
    svr.Get(R"(/question/(\d+))",[&control](const httplib::Request &_request, httplib::Response &_response){

                                    // !  尝试获取 matches[0] 等其他内容
        std::string number = _request.matches[1];  // mathches[1] 返回正则表达式匹配到的内容  \d+

        std::string html;
        control.OneQuestion(number,&html);
                                // !
        _response.set_content(html,"text/html;charset=utf-8");
    });

    
    
    svr.Get(R"(/static/(.*))",[&control](const httplib::Request &_request, httplib::Response &_response){
        std::string content = _request.matches[1];  // mathches[1] 返回正则表达式匹配到的内容  \d+
        std::string html;

        if(content.find("img")!=std::string::npos)
        {
            std::cout<<"test";
            std::string img = GetFileContentHeader("/home/ryan/Linux_code/Online_Judge/oj_server/template_html/"+content);
             _response.set_content(img,"image/jpeg");
             return;
        }
       

        ns_util::FileUtil::ReadFile("/home/ryan/Linux_code/Online_Judge/oj_server/template_html/"+content,&html,true);

        if(content.find("js")!=std::string::npos)
        _response.set_content(html,"application/x-javascript;charset=utf-8");
        else if(content.find("css")!=std::string::npos)
         _response.set_content(html,"text/css;charset=utf-8");
        else if(content.find("ttf")!=std::string::npos)
        _response.set_content(html,"font/ttf;charset=utf-8");
        else if(content.find("woff2")!=std::string::npos)
        _response.set_content(html,"font/woff2;charset=utf-8");
        else if(content.find("woff")!=std::string::npos)
        _response.set_content(html,"font/woff;charset=utf-8");

    });

    svr.Get(R"(/static/css/(.*))",[&control](const httplib::Request &_request, httplib::Response &_response){
        std::string content = _request.matches[1];  // mathches[1] 返回正则表达式匹配到的内容  \d+
        std::string html;
        ns_util::FileUtil::ReadFile("/home/ryan/Linux_code/Online_Judge/oj_server/template_html/js"+content,&html,true);
        _response.set_content(html,"text/css;charset=utf-8");
    });



    // svr.Get(R"(/home/ryan/Linux_code/Online_Judge/oj_server/template_html/js/jquery-3.7.1.min.js)",[&control](const httplib::Request &_request, httplib::Response &_response){
    //                                 // !  尝试获取 matches[0] 等其他内容
    //     // std::string number = _request.matches[1];  // mathches[1] 返回正则表达式匹配到的内容  \d+
    //     // std::string html;
    //     // control.OneQuestion(number,&html);
    //     //你在这里写,将这个内容作为响应打回去
    //     std::string html;
    //     std::cout<<"Test Get Js"<<std::endl;;
    //     ns_util::FileUtil::ReadFile("/home/ryan/Linux_code/Online_Judge/oj_server/template_html/js/jquery-3.7.1.min.js",&html,true);
    //                             // !
    //     _response.set_content(html,"application/x-javascript;charset=utf-8");
    // });


    svr.Post(R"(/judge/(\d+))",[&control](const httplib::Request &_request, httplib::Response &_response){
        std::string number = _request.matches[1];
        
        std::string result_json;
        control.Judge(number,_request.body,&result_json);
        _response.set_content(result_json,"application/json;charset=utf-8");
    });

    svr.Get(R"(/TableData)",[&control](const httplib::Request &_request, httplib::Response &_response){
        
    std::string result;

    control.AllQuestions_ToJson(result);
    
    _response.set_content(result,"application/json;charset=utf-8");
    });

    // 设置首页
    svr.set_base_dir("./wwwroot");  
    svr.listen("0.0.0.0",8880);

    return 0;
}


// ?  尝试获取
// //
// TODO
// *
// &
// ^
// !
// ~